<?php
	//Patient, subclass of User
	class Patient extends User{
		private $patient_bloodtype;
		private $patient_allergy;
		private $patient_benchmark;

		//Note: Constructor does not set ID however insert() and Patient::createUser() sets ID
		//      Use Patient::createUser() for manipulation of Patient
		
		//Constructor for Patient
		//
		//Param: username, password, email, firstname, lastname, 
		//		 gender, address, contact, date of birth, role, time
		//		 patient bloodtype = "NA", patient allergy = ""
		function __construct($user_username, $user_password, $user_email, 
								$user_firstname, $user_lastname, $user_gender, 
								$user_address, $user_contact, 
								$user_dob, $user_role, $user_time,
								$patient_bloodtype = "NA", $patient_allergy = "", $patient_benchmark = false) {

			parent::__construct($user_username, $user_password, $user_email, 
								$user_firstname, $user_lastname, $user_gender, 
								$user_address, $user_contact, 
								$user_dob, $user_role, $user_time);
			$this->setBloodtype($patient_bloodtype);
			$this->setAllergy($patient_allergy);
			$this->setBenchmark($patient_benchmark);
		}
		
		//Setter for blood type
		function setBloodtype($val) {
			$this->patient_bloodtype = $val;
		}
		//Getter for blood type
		function getBloodtype() {
			return $this->patient_bloodtype;
		}
		
		//Setter for allergy
		function setAllergy($val) {
			$this->patient_allergy = $val;
		}
		//Getter for allergy
		function getAllergy() {
			return $this->patient_allergy;
		}
		
		//Setter for Benchmarking
		function setBenchmark($val = false) {
			$this->patient_benchmark = $val;
			}				
		//Getter for Benchmarking
		function getBenchmark() {
			return $this->patient_benchmark;
		}				
		
		//Insert new Patient info into database
		//
		//Return: User ID or O
		function insert() {
			//Calls for User::insert() 
			$user_id = parent::insert();
			$db = Database::get();
			$query = "INSERT INTO " . PATIENT_TABLE . " 
				(user_id, patient_bloodtype, patient_allergy, patient_benchmark)
				VALUES(?, ?, ?, ?);";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$patient_bloodtype = base64_encode($this->getBloodtype());
				$patient_allergy = base64_encode($this->getAllergy());
				$patient_benchmark = $this->getBenchmark();
				
				$stmt->bind_param("dssi", $user_id, $patient_bloodtype, $patient_allergy, $patient_benchmark);
				$stmt->execute() or die('Invalid query for Patient: ' . $db->error);
				$stmt->close();
			}
			return intval($user_id);
		}

		//Update the database with new values in the Patient object		
		//
		//Return: true or false
		function update() {
			//Calls for User::update
			parent::update();
			$db = Database::get();
			$query = "UPDATE " . PATIENT_TABLE . " 
				SET patient_bloodtype = ?, patient_allergy = ?
				WHERE user_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$patient_bloodtype = base64_encode($this->getBloodtype());
				$patient_allergy = base64_encode($this->getAllergy());
				$user_id = parent::findID($this->getUsername());
				
				$stmt->bind_param("ssd", $patient_bloodtype, $patient_allergy, $user_id);
				$stmt->execute() or die('Invalid query for Patient: ' . $db->error);
				$stmt->close();
				
				return true;
			}			
			return false;
		}

		//Send patient's request to doctor from patient to form connection
		//
		//Param: doctor id, request note
		//Return: true or false
		function sendRequestTo($doctor_id, $request_note = "") {
			$user_id = parent::getUserID();
			$db = Database::get();
			$query = "INSERT INTO " . DOCTOR_PATIENT_TABLE . " 
				(doctor_id, patient_id, request_pending, request_note)
				VALUES(?, ?, ?, ?);";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$request_pending = true;
				
				$stmt->bind_param("ddds", $doctor_id, $user_id, $request_pending, $request_note);
				$stmt->execute() or die('Invalid query for Patient: ' . $db->error);
				$request_id = $stmt->insert_id;
				$stmt->close();
				
				//Create notification for the doctor to input into database
				$notification_message = str_replace('PERSON', User::findName($user_id), REQUEST_DOCTOR_MSG);
				$notification_type_id = Notification::findTypeID('request_doctor');
				$notification = new Notification($doctor_id, $notification_type_id, $notification_message, $user_id, $request_id, null);
				$notification->insert();
				
				return true;
			}
			return false;
		}		

		//Remove patient's request from doctor given the doctor id
		//
		//Param: doctor id
		//Return: true or false
		function removeRequestFrom($doctor_id) {
			$user_id = parent::getUserID();
			$db = Database::get();
			$query = "DELETE FROM " . DOCTOR_PATIENT_TABLE . " 
				WHERE doctor_id = ? AND patient_id = ?;";
			$stmt = $db->prepare($query);

			if ($stmt) {
				$request_pending = true;
				
				$stmt->bind_param("dd", $doctor_id, $user_id);
				$stmt->execute() or die('Invalid query for Patient: ' . $db->error);
				$stmt->close();
				
				//Create notification for the doctor to delete from database
				$notification_type_id = Notification::findTypeID('request_doctor');
				$notification_id = Notification::findID($doctor_id, $notification_type_id, $user_id);
				$notification = Notification::createNotification($notification_id);
				$notification->remove();
				
				return true;
			}

			return false;
		}			

		//Check patient's request pending of the patient given the doctor id
		//
		//Param: doctor id
		//Return: pending (boolean as int)
		function checkRequestPending($doctor_id) {
			$pending = -1;
			$user_id = parent::getUserID();
			$db = Database::get();
			$query = "SELECT request_pending FROM " . DOCTOR_PATIENT_TABLE . " 
				WHERE doctor_id = ? AND patient_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {			
				$stmt->bind_param("dd", $doctor_id, $user_id);
				$stmt->execute() or die('Invalid query for Patient: ' . $db->error);
				$stmt->bind_result($pending);
				$stmt->fetch() or $pending = -1;
				$stmt->close();
			}
			
			return intval($pending);
		}		

		//Get the list of doctors of the Patient
		//
		//Return: list of doctor
		function getDoctorList() {
			$user_id = parent::getUserID();
			$doctor_list = self::doctorList($user_id);	
			return $doctor_list;
		}		

		//Get list of DataLog of the user
		//
		//Return: List of DataLog		
		function getDataLogList() {
			return DataLog::getDataLogList($this->getUserID());
		}		

		//Get list of DataLog per day of the user
		//
		//Return: List of DataLog per day	
		function getDataLogListForTypePerDay($datalog_type_id) {
			return DataLog::getDataLogListForTypePerDay($this->getUserID(), $datalog_type_id);
		}

		//Get list of Symptom of the user
		//
		//Return: List of Symptom	
		function getSymptomList() {
			return Symptom::getSymptomList($this->getUserID());
		}	
		
		//Get list of Food of the user
		//
		//Return: List of Food	
		function getFoodList() {
			return Food::getFoodList($this->getUserID());
		}
		
		//Get list of Food calories per day of the user
		//
		//Return: List of Food calories per day
		function getFoodCaloriesPerDay() {
			return Food::getFoodCaloriesPerDay($this->getUserID());
		}				
		
		//Set request benchmark of the given patient
		//
		//Param: value (true or false)
		//Return: true or false
		function setPatientBenchmark($val) {
			$user_id = parent::getUserID();
			$db = Database::get();
			$query = "UPDATE " . PATIENT_TABLE . "
				SET patient_benchmark = ?
				WHERE user_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {		
				$stmt->bind_param("dd", $val, $user_id);
				$stmt->execute() or die('Invalid query for Patient: ' . $db->error);
				$stmt->close();
				
				return true;
			}
			
			return false;
		}		
		
		//Create Patient object given the ID by taking information from the database
		//Information taken from the database: username, email, first name, last name,
		//	gender, address, contact, date of birth (dob), role, time, valid token,
		//	bloodtype, allergy, benchmark (true or false)
		//
		//Param: user id
		//Return: Patient object			
		static function createUser($id) {
			$db = Database::get();
			$query = "SELECT * FROM " . PATIENT_TABLE . " INNER JOIN " . USER_TABLE . "
					  ON user.user_id = patient.user_id
					  WHERE patient.user_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$stmt->bind_param("d", $id);
				$stmt->execute() or die('Invalid query for Patient: ' . $db->error);
				$result = $stmt->get_result();
				$patient_row = null;
				if ($row = $result->fetch_assoc()) {
					$patient_row = $row;
				} 
				$stmt->close();
			} else {
				die('Invalid query for Patient: ' . $db->error);
			}
			
			$user = null;
			if ($patient_row !== null) {
				//Decode start
				$patient_bloodtype = base64_decode($patient_row['patient_bloodtype']);
				$patient_allergy = base64_decode($patient_row['patient_allergy']);
				//Decode end
				$patient_benchmark = $patient_row['patient_benchmark'];
				
				$user_username = $patient_row['user_username'];
				$user_email = $patient_row['user_email'];
				
				$user_firstname = $patient_row['user_firstname'];
				$user_lastname = $patient_row['user_lastname'];
				$user_gender = $patient_row['user_gender'];				
				//Decode start
				$user_address = base64_decode($patient_row['user_address']);
				$user_contact = base64_decode($patient_row['user_contact']);
				$user_dob = base64_decode($patient_row['user_dob']);
				//Decode end
				$user_role = $patient_row['user_role'];		
				$user_time = $patient_row['created_at'];
				
				$user_valid = $patient_row['user_valid'];
				
				$user = new Patient($user_username, null, $user_email, $user_firstname, $user_lastname, 
							$user_gender, $user_address, $user_contact, $user_dob, $user_role, $user_time,
							$patient_bloodtype, $patient_allergy, $patient_benchmark);
				$user->setUserID($id);
				$user->setValid($user_valid);
				}
			
			return $user;
		}
		
		//Find a Patient given the Patient ID from the database
		//Use this when viewing as a third party. If not, please use Patient::createUser() instead
		//
		//Param: patient id
		//Return: patient info (array)
		static function findPatient($patient_id) {
			$patient = null;
			$db = Database::get();
			$query = "SELECT " . PATIENT_TABLE. ".user_id, 
					user_firstname, user_lastname,  user_email, user_gender, user_address, user_contact, user_dob,
					patient_bloodtype, patient_allergy
					FROM " . PATIENT_TABLE . "
					INNER JOIN " . USER_TABLE. " 
					ON " . USER_TABLE . ".user_id=" . PATIENT_TABLE. ".user_id
					WHERE " . PATIENT_TABLE. ".user_id=?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$stmt->bind_param("d", $patient_id);
				$stmt->execute() or die('Invalid query for Patient: ' . $db->error);
				$result = $stmt->get_result();
				if ($row = $result->fetch_assoc()) {
					$patient = $row;
				} 
				$stmt->close();
			} else {
				die('Invalid query for Patient: ' . $db->error);
			}
			//Decode
			if ($patient !== null) {
				$patient['user_address'] = base64_decode($patient['user_address']);
				$patient['user_contact'] = base64_decode($patient['user_contact']);
				$patient['user_dob'] = base64_decode($patient['user_dob']);
				$patient['patient_bloodtype'] = base64_decode($patient['patient_bloodtype']);
				$patient['patient_allergy'] = base64_decode($patient['patient_allergy']);
			}			
			
			return $patient;
		}
		
		//Get the list of doctors of the Patient
		//
		//Param: patient id
		//Return: list of doctor
		static function doctorList($id) {
			$user_id = $id;
			$request_list = null;
			$db = Database::get();
			$query = "SELECT * FROM " . DOCTOR_PATIENT_TABLE . " 
				WHERE patient_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {			
				$stmt->bind_param("d", $user_id);
				$stmt->execute() or die('Invalid query for Patient: ' . $db->error);
				$result = $stmt->get_result();
				while($row = $result->fetch_assoc()) {
					$request_list[] = $row;
				} 
				$stmt->close();
			}	
			return $request_list;
		}	

		//Get the list of doctors ID of the Patient
		//
		//Param: patient id
		//Return: list of doctor ID	
		static function doctorIDList($id) {
			$user_id = $id;
			$id_list = null;
			$db = Database::get();
			$query = "SELECT doctor_id FROM " . DOCTOR_PATIENT_TABLE . " 
				WHERE patient_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {			
				$stmt->bind_param("d", $user_id);
				$stmt->execute() or die('Invalid query for Patient: ' . $db->error);
				$result = $stmt->get_result();
				while($row = $result->fetch_assoc()) {
					$id_list[] = intval($row['doctor_id']);
				} 
				$stmt->close();
			}
			
			return $id_list;
		}	
		
		//Check the status of the doctor-patient relationship
		//
		//Param: doctor id, patient id
		//Return: true or false
		static function checkDoctor($doctor_id, $patient_id) {
			$pending = -1;
			$db = Database::get();
			$query = "SELECT request_pending FROM " . DOCTOR_PATIENT_TABLE . "
					  WHERE doctor_id = ? AND patient_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$stmt->bind_param("dd", $doctor_id, $patient_id);
				$stmt->execute() or die('Invalid query for Patient: ' . $db->error);
				$stmt->bind_result($pending);
				$stmt->fetch() or $pending = -1;
				$stmt->close();
			} else {
				die('Invalid query for Patient: ' . $db->error);
			}
			
			if (intval($pending) === 0) {
				return true;
			}
			return false;
		}	
		
		//Find request ID given the patient ID
		//
		//Param: patient id
		//Return: request id	
		static function findRequestID($id) {
			$db = Database::get();
			$request_id = 0;
			
			$query = "SELECT request_id FROM " . DOCTOR_PATIENT_TABLE . "
					  WHERE patient_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$stmt->bind_param("d", $id);
				$stmt->execute() or die('Invalid query for User: ' . $db->error);
				$stmt->bind_result($request_id);
				$stmt->fetch() or $request_id = 0;
				$stmt->close();
			} else {
				die('Invalid query for User: ' . $db->error);
			}
			return intval($request_id);
		}
		
	}
?>